package ruifight.member.controller.common.fileUtil;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Iterator;

import com.alibaba.druid.util.Base64;

/**   
*    
* 类描述：base64 工具类  
* 创建人：浅缘0419   
* 创建时间：2018年11月21日 下午5:04:44         
* 修改备注：   
* @version    
*    
*/
public class Base64Utils {

	 private static Base64Utils utils = null;

	    private Base64Utils(){

	    }
	    /**     
	    * 方法描述： 单利 ，懒汉模式  
	    * @return 
	    * 创建人：浅缘0419   
	    * 创建时间：2018年11月23日 上午9:43:10              
	    */
	    public static Base64Utils getInstance(){
	        if(utils == null){
	            synchronized (Base64Utils.class) {
	                if(utils == null ){
	                    utils = new Base64Utils();
	                }
	            }
	        }
	        return utils;
	    }
	    /**     
	    * 方法描述：  获取文件的大小 
	    * @param inFile
	    * @return 
	    * 创建人：浅缘0419   
	    * 创建时间：2018年11月23日 上午9:43:00              
	    */
	    public static int getFileSize(File inFile){
	        InputStream in = null;
	        try {
	            in = new FileInputStream(inFile);
	            //文件长度
	            int len = in.available();
	            return len;
	        }catch (Exception e) {
	            // TODO: handle exception
	        }finally{
	            try {
	                in.close();
	            } catch (IOException e) {
	                // TODO Auto-generated catch block
	                e.printStackTrace();
	            }
	        }
	        return -1;
	    }

	    /**     
	    * 方法描述：将文件转化为base64   
	    * @param inFile
	    * @return 
	    * 创建人：浅缘0419   
	    * 创建时间：2018年11月23日 上午9:43:30              
	    */
	    public static String file2Base64(File inFile){
	    	String result = "";
	    	if(checkFileType(inFile)) {
	        //将文件转化为字节码
	        byte [] bytes = copyFile2Byte(inFile);
	        if(bytes == null){
	            return null;
	        }

	        //base64,将字节码转化为base64的字符串
	        result = Base64.byteArrayToBase64(bytes);
	    	}else {
	    		String suffix = inFile.getName().substring(inFile.getName().lastIndexOf("."));
		    	throw new CustomException("不支持这种"+suffix+"格式");
	    	}
	        return result;
	    }

	    /**     
	    * 方法描述：   将文件转化为字节码
	    * @param inFile
	    * @return 
	    * 创建人：浅缘0419   
	    * 创建时间：2018年11月23日 上午9:43:42              
	    */
	    public static byte [] copyFile2Byte(File inFile){
	        InputStream in = null;
	        byte [] bytes = null ;
	        try {
	        	if(checkFileType(inFile)) {
		            in = new FileInputStream(inFile);
		            //文件长度
		            int len = in.available();
	
		            //定义数组
		            bytes = new byte[len];
	
		            //读取到数组里面
		            in.read(bytes);
	        	}else {
	        		String suffix = inFile.getName().substring(inFile.getName().lastIndexOf("."));
			    	throw new CustomException("不支持这种"+suffix+"格式");
	        	}
	        } catch (Exception e) {
	            e.printStackTrace();
	        }finally{
	            try {
	                if(in != null){
	                    in.close();
	                }
	            } catch (Exception e) {
	                e.printStackTrace();
	            }
	        }
		    return bytes;
	    }
	    /**     
	    * 方法描述：   将字符串转化为文件
	    * @param strBase64 base64 编码的文件
	    * @param outFile  输出的目标文件地址
	    * @return 
	    * 创建人：浅缘0419   
	    * 创建时间：2018年11月23日 上午9:43:55              
	    */
	    public static boolean base64ToFile(String strBase64,File outFile){
	        try {
	            // 解码，然后将字节转换为文件
	            byte[] bytes = Base64.base64ToByteArray(strBase64); // 将字符串转换为byte数组
	            return copyByte2File(bytes,outFile);
	        } catch (Exception ioe) {
	            ioe.printStackTrace();
	            return false;
	        }
	    }
	    /**     
	    * 方法描述： 将字节码转化为文件  
	    * @param bytes
	    * @param file
	    * @return 
	    * 创建人：浅缘0419   
	    * 创建时间：2018年11月23日 上午9:44:25              
	    */
	    private static boolean copyByte2File(byte [] bytes,File file){
	        FileOutputStream  out = null;
	        try {
	            //转化为输入流
	            ByteArrayInputStream in = new ByteArrayInputStream(bytes);

	            //写出文件
	            byte[] buffer = new byte[1024];

	            out = new FileOutputStream(file);

	            //写文件
	            int len = 0;
	            while ((len = in.read(buffer)) != -1) {
	                out.write(buffer, 0, len); // 文件写操作
	            }
	            return true;
	        } catch (Exception e) {
	            // TODO Auto-generated catch block
	            e.printStackTrace();
	        }finally{
	            try {
	                if(out != null){
	                    out.close();
	                }
	            } catch (IOException e) {
	                // TODO Auto-generated catch block
	                e.printStackTrace();
	            }
	        }
	        return false;
	    }
	
	    /**     
	    * 方法描述：   通过图片base64流算出图的大小(返回字节大小)
	    * @param image
	    * @return 
	    * 创建人：浅缘0419   
	    * 创建时间：2018年11月22日 下午6:18:14              
	    */
	    public static Long getImageSizeByte(String image){
	        String str=image.substring(22); // 1.需要计算文件流大小，首先把头部的data:image/png;base64,（注意有逗号）去掉。
	        long equalIndex= str.indexOf("=");//2.找到等号，把等号也去掉
	        if(str.indexOf("=")>0) {
	            str=str.substring(0, (int) equalIndex);
	        }
	        long strLength=str.length();//3.原来的字符流大小，单位为字节
	        long size=strLength-(strLength/8)*2;//4.计算后得到的文件流大小，单位为字节
	        return size;
	    }
	    
	    /**     
	    * 方法描述：   通过base64流算出文件的大小 返回一个String类型
	    * @param image
	    * @return 
	    * 创建人：浅缘0419   
	    * 创建时间：2018年11月22日 下午6:18:14              
	    */
	    public static String getImageSizeString(String image){
	        String str=image.substring(22); // 1.需要计算文件流大小，首先把头部的data:image/png;base64,（注意有逗号）去掉。
	        long equalIndex= str.indexOf("=");//2.找到等号，把等号也去掉
	        if(str.indexOf("=")>0) {
	            str=str.substring(0, (int) equalIndex);
	        }
	        long strLength=str.length();//3.原来的字符流大小，单位为字节
	        long size=strLength-(strLength/8)*2;//4.计算后得到的文件流大小，单位为字节
	        return getPrintSize(size);
	    }
	    
	    /**     
	    * 方法描述：   字节转大小
	    * @param size
	    * @return 
	    * 创建人：浅缘0419   
	    * 创建时间：2018年11月22日 下午6:21:04              
	    */
	    public static String getPrintSize(long size) {
	        //如果字节数少于1024，则直接以B为单位，否则先除于1024，后3位因太少无意义
	        if (size < 1024) {
	          return String.valueOf(size) + "B";
	        } else {
	          size = size / 1024;
	        }
	        //如果原字节数除于1024之后，少于1024，则可以直接以KB作为单位
	        //因为还没有到达要使用另一个单位的时候
	        //接下去以此类推
	        if (size < 1024) {
	          return String.valueOf(size) + "KB";
	        } else {
	          size = size / 1024;
	        }
	        if (size < 1024) {
	          //因为如果以MB为单位的话，要保留最后1位小数，
	          //因此，把此数乘以100之后再取余
	          size = size * 100;
	          return String.valueOf((size / 100)) + "."
	              + String.valueOf((size % 100)) + "MB";
	        } else {
	          //否则如果要以GB为单位的，先除于1024再作同样的处理
	          size = size * 100 / 1024;
	          return String.valueOf((size / 100)) + "."
	              + String.valueOf((size % 100)) + "GB";
	        }
	      }
	    
	    /**     
	    * 方法描述：   讲照片流压缩然后转化成base64(图片尺寸不变，压缩图片文件大小)
		* @param file 传来的文件流
		* @param maxSize 压缩到指定最大值kb
		* @param ratio 按照质量值压缩 0 - 1
	    * @return 
	    * 创建人：浅缘0419   
	    * 创建时间：2018年11月23日 上午10:37:57              
	    */
	    public static String photoFileToBase64(File inFile,Integer maxSize,double ratio){
	    	String result = "";
	    	if(checkFileImageType(inFile)) {
	    		 //将文件转化为字节码
		        byte [] bytes = copyFile2Byte(ReduceFile.reduceFileToAssignSize(inFile, maxSize, ratio));
		        if(bytes == null){
		            return null;
		        }
		        //base64,将字节码转化为base64的字符串
		        result = Base64.byteArrayToBase64(bytes);
	    	}else {
	    		String suffix = inFile.getName().substring(inFile.getName().lastIndexOf("."));
		    	throw new CustomException("不支持这种"+suffix+"格式");
	    	}
	        return result;
	    }
	    
	    /**     
	    * 方法描述：   判断文件流是否为照片文件流
	    * @param file
	    * @return 
	    * 创建人：浅缘0419   
	    * 创建时间：2018年11月23日 下午2:28:32              
	    */
	    public static boolean checkFileImageType(File file) {
	    	String suffix = file.getName().substring(file.getName().lastIndexOf("."));
			Iterator<String> type = Arrays.asList(FileConfigUtil.allowImage).iterator();
			while (type.hasNext()) {
				String ext = type.next();
				if (suffix.toLowerCase().endsWith(ext)) {
					return true;
				}
			}
			return false;
		}
	    
	    /**     
	    * 方法描述：   判断文件流是否为系统支持的文件流
	    * @param file
	    * @return 
	    * 创建人：浅缘0419   
	    * 创建时间：2018年11月23日 下午2:58:59              
	    */
	    public static boolean checkFileType(File file) {
	    	String suffix = file.getName().substring(file.getName().lastIndexOf("."));
			Iterator<String> type = Arrays.asList(FileConfigUtil.allowFiles).iterator();
			while (type.hasNext()) {
				String ext = type.next();
				if (suffix.toLowerCase().endsWith(ext)) {
					return true;
				}
			}
			return false;
		}
	    
}
